package com.test.rsa;

import com.google.common.base.Strings;
import org.apache.shiro.codec.Base64;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

/**
 * 1024位密钥，最大加密长度117byte（128-11），加密后byte数组长度128（2的7次幂）
 * 2048位密钥，最大加密长度245byte（256-11），加密后byte数组长度256（2的8次幂）
 * 4096位密钥，最大加密长度501byte（512-11），加密后byte数组长度512（2的9次幂）
 */
public class RSADemo {

    public static void main(String[] args) throws Exception {
        // 创建RSA密钥对类
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对
        keyPairGen.initialize(4096, new SecureRandom());
        KeyPair keyPair = keyPairGen.generateKeyPair();

        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
//        System.out.println(Strings.lenientFormat("PRIVATE_KEY=%s\n ==============================", Base64.encodeToString(privateKey.getEncoded())));
//        System.out.println(Strings.lenientFormat("PUBLIC_KEY=%s\n ==============================", Base64.encodeToString(publicKey.getEncoded())));

        String plainText = "哈喽哈喽哈喽哈喽哈喽哈喽";
        System.out.println(plainText.getBytes(StandardCharsets.UTF_8).length);
        byte[] bytes = encrypt(publicKey, plainText.getBytes(StandardCharsets.UTF_8));
        System.out.println(Strings.lenientFormat("CipherText=%s", bytes.length));
        String s = Base64.encodeToString(bytes);
        System.out.println(s);

        String ss = new String(decrypt(privateKey, Base64.decode(s)), StandardCharsets.UTF_8);
        System.out.println(ss);
    }

    /**
     * 公钥加密
     */
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(plainTextData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此加密算法");
        }
    }

    /**
     * 私钥解密
     */
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] output = cipher.doFinal(cipherData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此解密算法");
        }
    }


    /**
     * 私钥加密过程
     */
    public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
            throws Exception {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] output = cipher.doFinal(plainTextData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此加密算法");
        }
    }

    /**
     * 公钥解密过程
     */
    public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
            throws Exception {
        try {
            // 使用默认RSA
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(cipherData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此解密算法");
        }
    }
}
